import { Checksum, SourceData } from "@smithy/types";
import { StringEncoding } from "@smithy/util-buffer-from";
import { buffer, crypto} from "@ohos/node-polyfill";

/**
 * @internal
 */
export class Hash implements Checksum {
  private readonly algorithmIdentifier: string;
  private readonly secret?: SourceData;
  private hash!: crypto.NodeHash | crypto.Hmac;

  constructor(algorithmIdentifier: string, secret?: SourceData) {
    this.algorithmIdentifier = algorithmIdentifier;
    this.secret = secret;
    this.reset();
  }

  update(toHash: SourceData, encoding?: "utf8" | "ascii" | "latin1"): void {
    this.hash.update(castSourceData(toHash,encoding));
  }

  digest(): Promise<Uint8Array> {
    return Promise.resolve(this.hash.digest());
  }

  reset(): void {
    crypto.createHash
    this.hash = this.secret
      ? crypto.createHmac(this.algorithmIdentifier, castSourceData(this.secret))
      : crypto.createHash(this.algorithmIdentifier);
  }
}

function castSourceData(toCast: SourceData, encoding?: StringEncoding): buffer.Buffer {
  if (buffer.Buffer.isBuffer(toCast)) {
    return toCast;
  }
  if (typeof toCast==='string') {
    return encoding ? buffer.Buffer.from(toCast, encoding) : buffer.Buffer.from(toCast);
  }else if (toCast instanceof ArrayBuffer){
    return buffer.Buffer.from(toCast)
  }else if (ArrayBuffer.isView(toCast)){
    const buf = new Uint8Array(toCast.buffer,toCast.byteOffset,toCast.byteLength/Uint8Array.BYTES_PER_ELEMENT)
    return buffer.Buffer.from(buf.buffer)
  }
}